package org.iteam.mina.codec;

import java.nio.charset.Charset;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.iteam.mina.Constant;
import org.iteam.mina.message.BaseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 通用编码器
 * 
 * @author ke.wen
 *
 */
public class MessageEncoder extends ProtocolEncoderAdapter {
	private static Logger log = LoggerFactory.getLogger(Constant.MINA_LOG_NAME);

	private Charset charset;

	public MessageEncoder(Charset charset) {
		this.charset = charset;
	}

	/**
	 * 编码
	 * 
	 * @协议格式 总数据长度[4]命令[4]规则[4]消息协议版本[4]消息流水号[32]标识符[32]数据长度[4]数据内容
	 *       [根据数据长度定]签名数据长度[4]签名数据内容 [根据签名数据长度定]
	 */
	public void encode(IoSession session, Object object, ProtocolEncoderOutput out) throws Exception {
		if (object != null && session.isConnected()) {
			IoBuffer buf = null;
			// IoBuffer buf = IoBuffer.allocate(100).setAutoExpand(true);
			if (object instanceof BaseMessage) {// 请求协议
				BaseMessage mpReq = (BaseMessage) object;
				// 01-->获取总报头长度 {总数据长度[4]命令[4]规则[4]消息协议版本[4]消息流水号[32]标识符[32]}
				int messageLength = 4 * 3 + 32 * 2;
				// 02-->获取数据内容
				byte[] bs_content = null;
				int bs_content_length = 0;
				if (mpReq.getContent() != null && mpReq.getContent().length > 0) {
					bs_content = mpReq.getContent();
					bs_content_length = bs_content.length;
					messageLength += bs_content_length;
				}
				// 03-->获取校验信息
				byte[] bs_verify = null;
				int bs_verify_length = 0;
				if (mpReq.getVerify() != null && mpReq.getVerify().length > 0) {
					bs_verify = mpReq.getVerify();
					bs_verify_length = bs_verify.length;
					messageLength += bs_verify_length;
				}

				mpReq.setLength(messageLength);

				buf = IoBuffer.allocate(messageLength + 4);
				// 设置数据报文总长度
				buf.putInt(messageLength);
				// 设置命令
				buf.putInt(mpReq.getCmd());
				// 设置规则
				buf.putInt(mpReq.getRule());
				// 设置消息协议版本
				buf.putInt(mpReq.getVer());
				// 设置消息流水号
				buf.putString(mpReq.getSeq(), 32, charset.newEncoder());
				// 设置令牌
				buf.putString(mpReq.getToken(), 32, charset.newEncoder());

				// 设置数据内容
				if (bs_content_length > 0) {
					buf.put(bs_content);
				}
				// 设置校验数据
				if (bs_verify_length > 0) {
					buf.put(bs_verify);
				}
			} else {
				throw new Exception("未定义的协议数据类型");
			}
			buf.flip();
			out.write(buf);
			out.flush();

		} else {
			log.error("消息内容错误 object != null && session.isConnected()");
		}
	}
}